home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / OpenGL / OPENGL2.EXE / _SETUP.1 / sdib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-21  |  16.9 KB  |  688 lines

  1. /*
  2. ** Simple example of rendering to a Windows DIB (Device Independent Bitmap)
  3. */
  4. #include <windows.h>
  5. #include <math.h>
  6. #include <GL/gl.h>
  7.  
  8. #if !defined(M_PI)
  9. #define M_PI 3.14159265F
  10. #endif
  11.  
  12. char *className = "OpenGL";
  13. char *windowName = "Simple DIB Example";
  14. int winX = 0, winY = 0;
  15. int winWidth = 200, winHeight = 200;
  16.  
  17. HDC hDC;
  18. HDC hDCWindow;
  19. HGLRC hGLRC;
  20. HPALETTE hPalette;
  21. HBITMAP hBitmap, hOldBitmap;
  22.  
  23. void (*idleFunc)(void);
  24.  
  25. BOOL colorIndexMode = TRUE;
  26. BOOL doubleBuffered = FALSE;
  27. BOOL renderToDIB = TRUE;
  28.  
  29. DWORD rmask, gmask, bmask;
  30.  
  31. /* Struct used to manage color ramps */
  32. struct colorIndexState {
  33.     GLfloat amb[3];    /* ambient color / bottom of ramp */
  34.     GLfloat diff[3];    /* diffuse color / middle of ramp */
  35.     GLfloat spec[3];    /* specular color / top of ramp */
  36.     GLfloat ratio;    /* ratio of diffuse to specular in ramp */
  37.     GLint indexes[3];    /* where ramp was placed in palette */
  38. };
  39.  
  40. /*
  41. ** Each entry in this array corresponds to a color ramp in the
  42. ** palette.  The indexes member of each struct is updated to
  43. ** reflect the placement of the color ramp in the palette.
  44. */
  45. #define NUM_COLORS (sizeof(colors) / sizeof(colors[0]))
  46. struct colorIndexState colors[] = {
  47.     {
  48.         { 0.0F, 0.0F, 0.0F },
  49.         { 0.1F, 0.6F, 0.3F },
  50.         { 1.0F, 1.0F, 1.0F },
  51.         0.75F, { 0, 0, 0 },
  52.     },
  53.     {
  54.         { 0.0F, 0.0F, 0.0F },
  55.         { 0.0F, 0.2F, 0.5F },
  56.         { 1.0F, 1.0F, 1.0F },
  57.         0.75F, { 0, 0, 0 },
  58.     },
  59.     {
  60.         { 0.0F, 0.05F, 0.05F },
  61.         { 0.6F, 0.0F, 0.8F },
  62.         { 1.0F, 1.0F, 1.0F },
  63.         0.75F, { 0, 0, 0 },
  64.     },
  65. };
  66.  
  67. void
  68. drawTorus(void)
  69. {
  70.     int numMajor = 32;
  71.     int numMinor = 24;
  72.     float majorRadius = 0.6F;
  73.     float minorRadius = 0.2F;
  74.     double majorStep = 2.0F*M_PI / numMajor;
  75.     double minorStep = 2.0F*M_PI / numMinor;
  76.     int i, j;
  77.  
  78.     for (i=0; i<numMajor; ++i) {
  79.     double a0 = i * majorStep;
  80.     double a1 = a0 + majorStep;
  81.     GLfloat x0 = (GLfloat) cos(a0);
  82.     GLfloat y0 = (GLfloat) sin(a0);
  83.     GLfloat x1 = (GLfloat) cos(a1);
  84.     GLfloat y1 = (GLfloat) sin(a1);
  85.  
  86.     if (i & 1) {
  87.         glColor3fv(colors[0].diff);
  88.         glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, colors[0].indexes);
  89.     } else {
  90.         glColor3fv(colors[1].diff);
  91.         glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, colors[1].indexes);
  92.     }
  93.  
  94.     glBegin(GL_TRIANGLE_STRIP);
  95.     for (j=0; j<=numMinor; ++j) {
  96.         double b = j * minorStep;
  97.         GLfloat c = (GLfloat) cos(b);
  98.         GLfloat r = minorRadius * c + majorRadius;
  99.         GLfloat z = minorRadius * (GLfloat) sin(b);
  100.  
  101.         glNormal3f(x0*c, y0*c, z/minorRadius);
  102.         glVertex3f(x0*r, y0*r, z);
  103.  
  104.         glNormal3f(x1*c, y1*c, z/minorRadius);
  105.         glVertex3f(x1*r, y1*r, z);
  106.     }
  107.     glEnd();
  108.     }
  109. }
  110.  
  111. /*****************************************************************/
  112.  
  113. void
  114. setProjection(void)
  115. {
  116.     glMatrixMode(GL_PROJECTION);
  117.     glLoadIdentity();
  118.     /*
  119.     ** Preserve the aspect ratio of objects in the scene.
  120.     */
  121.     if (winWidth > winHeight) {
  122.     GLfloat aspect = (GLfloat) winWidth / (GLfloat) winHeight;
  123.     glFrustum(-0.5F*aspect, 0.5F*aspect, -0.5F, 0.5F, 1.0F, 3.0F);
  124.     } else {
  125.     GLfloat aspect = (GLfloat) winHeight / (GLfloat) winWidth;
  126.     glFrustum(-0.5F, 0.5F, -0.5F*aspect, 0.5F*aspect, 1.0F, 3.0F);
  127.     }
  128.     glMatrixMode(GL_MODELVIEW);
  129. }
  130.  
  131. void
  132. init(void)
  133. {
  134.     GLfloat matShine = 20.00F;
  135.     GLfloat light0Pos[4] = { 0.70F, 0.70F, 1.25F, 0.00F };
  136.  
  137.     glClearColor(colors[2].diff[0], colors[2].diff[1], colors[2].diff[2], 1.0F);
  138.     glClearIndex((GLfloat) colors[2].indexes[1]);
  139.  
  140.     setProjection();
  141.     glTranslatef(0.0F, 0.0F, -2.0F);
  142.  
  143.     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
  144.     glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  145.     glEnable(GL_LIGHT0);
  146.  
  147.     glEnable(GL_LIGHTING);
  148.     glEnable(GL_DEPTH_TEST);
  149.  
  150.     if (!colorIndexMode) {
  151.     glEnable(GL_COLOR_MATERIAL);
  152.     }
  153. }
  154.  
  155. void
  156. doRedraw(void)
  157. {
  158.     static GLfloat x, y, z;
  159.  
  160.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  161.  
  162.     glPushMatrix();
  163.     glRotatef(x, 1.0F, 0.0F, 0.0F);
  164.     glRotatef(y, 0.0F, 1.0F, 0.0F);
  165.     glRotatef(z, 0.0F, 0.0F, 1.0F);
  166.  
  167.     drawTorus();
  168.  
  169.     glPopMatrix();
  170.  
  171.     if (renderToDIB) {
  172.     glFinish();
  173.     BitBlt(hDCWindow, 0, 0, winWidth, winHeight, hDC, 0, 0, SRCCOPY);
  174.     GdiFlush();
  175.     } else {
  176.     SwapBuffers(hDC);
  177.     }
  178.  
  179.     x += 5.0F;
  180.     if (x > 360.0F) x -= 360.0F;
  181.     y += 7.0F;
  182.     if (y > 360.0F) y -= 360.0F;
  183.     z += 9.0F;
  184.     if (z > 360.0F) z -= 360.0F;
  185. }
  186.  
  187. void
  188. redraw(void)
  189. {
  190.     idleFunc = doRedraw;
  191. }
  192.  
  193. void
  194. resize(void)
  195. {
  196.     setProjection();
  197.     glViewport(0, 0, winWidth, winHeight);
  198. }
  199.  
  200. /*****************************************************************/
  201.  
  202. void
  203. setupDIB(HDC hDC)
  204. {
  205.     BITMAPINFO *bmInfo;
  206.     BITMAPINFOHEADER *bmHeader;
  207.     UINT usage;
  208.     VOID *base;
  209.     int bmiSize;
  210.     int bitsPerPixel;
  211.  
  212.     bmiSize = sizeof(*bmInfo);
  213.     bitsPerPixel = colorIndexMode ? 8 : GetDeviceCaps(hDC, BITSPIXEL);
  214.  
  215.     switch (bitsPerPixel) {
  216.     case 8:
  217.     /* bmiColors is 256 WORD palette indices */
  218.     bmiSize += (256 * sizeof(WORD)) - sizeof(RGBQUAD);
  219.     break;
  220.     case 16:
  221.     /* bmiColors is 3 WORD component masks */
  222.     bmiSize += (3 * sizeof(DWORD)) - sizeof(RGBQUAD);
  223.     break;
  224.     case 24:
  225.     case 32:
  226.     default:
  227.     /* bmiColors not used */
  228.     break;
  229.     }
  230.  
  231.     bmInfo = (BITMAPINFO *) calloc(1, bmiSize);
  232.     bmHeader = &bmInfo->bmiHeader;
  233.  
  234.     bmHeader->biSize = sizeof(*bmHeader);
  235.     bmHeader->biWidth = winWidth;
  236.     bmHeader->biHeight = winHeight;
  237.     bmHeader->biPlanes = 1;            /* must be 1 */
  238.     bmHeader->biBitCount = bitsPerPixel;
  239.     bmHeader->biXPelsPerMeter = 0;
  240.     bmHeader->biYPelsPerMeter = 0;
  241.     bmHeader->biClrUsed = 0;            /* all are used */
  242.     bmHeader->biClrImportant = 0;        /* all are important */
  243.  
  244.     switch (bitsPerPixel) {
  245.     case 8:
  246.     bmHeader->biCompression = BI_RGB;
  247.     bmHeader->biSizeImage = 0;
  248.     usage = DIB_PAL_COLORS;
  249.     /* bmiColors is 256 WORD palette indices */
  250.     {
  251.         WORD *palIndex = (WORD *) &bmInfo->bmiColors[0];
  252.         int i;
  253.  
  254.         for (i=0; i<256; i++) {
  255.         palIndex[i] = i;
  256.         }
  257.     }
  258.     break;
  259.     case 16:
  260.     bmHeader->biCompression = BI_BITFIELDS;
  261.     bmHeader->biSizeImage = 0;
  262.     usage = DIB_RGB_COLORS;
  263.     /* bmiColors is 3 WORD component masks */
  264.     {
  265.         DWORD *compMask = (DWORD *) &bmInfo->bmiColors[0];
  266.  
  267.         compMask[0] = rmask;
  268.         compMask[1] = gmask;
  269.         compMask[2] = bmask;
  270.     }
  271.     break;
  272.     case 24:
  273.     case 32:
  274.     default:
  275.     bmHeader->biCompression = BI_RGB;
  276.     bmHeader->biSizeImage = 0;
  277.     usage = DIB_RGB_COLORS;
  278.     /* bmiColors not used */
  279.     break;
  280.     }
  281.  
  282.     hBitmap = CreateDIBSection(hDC, bmInfo, usage, &base, NULL, 0);
  283.     if (hBitmap == NULL) {
  284.     (void) MessageBox(WindowFromDC(hDC),
  285.         "Failed to create DIBSection.",
  286.         "OpenGL application error",
  287.         MB_ICONERROR | MB_OK);
  288.     exit(1);
  289.     }
  290.  
  291.     hOldBitmap = SelectObject(hDC, hBitmap);
  292.  
  293.     free(bmInfo);
  294. }
  295.  
  296. void
  297. resizeDIB(HDC hDC)
  298. {
  299.     SelectObject(hDC, hOldBitmap);
  300.     DeleteObject(hBitmap);
  301.     setupDIB(hDC);
  302.     // This is necessary so the context will notice that the DIB has changed
  303.     wglMakeCurrent(hDC, hGLRC);
  304. }
  305.  
  306. void
  307. setupPalette(HDC hDC)
  308. {
  309.     PIXELFORMATDESCRIPTOR pfd;
  310.     LOGPALETTE* pPal;
  311.     int pixelFormat = GetPixelFormat(hDC);
  312.     int paletteSize;
  313.  
  314.     DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  315.  
  316.     /*
  317.     ** Determine if a palette is needed and if so what size.
  318.     */
  319.     if (pfd.dwFlags & PFD_NEED_PALETTE) {
  320.     paletteSize = 1 << pfd.cColorBits;
  321.     } else if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
  322.     paletteSize = 256;
  323.     } else {
  324.     rmask = ((1<<pfd.cRedBits)-1)   << pfd.cRedShift;
  325.     gmask = ((1<<pfd.cGreenBits)-1) << pfd.cGreenShift;
  326.     bmask = ((1<<pfd.cBlueBits)-1)  << pfd.cBlueShift;
  327.     return;
  328.     }
  329.  
  330.     pPal = (LOGPALETTE*)
  331.     malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
  332.     pPal->palVersion = 0x300;
  333.     pPal->palNumEntries = paletteSize;
  334.  
  335.     if (pfd.iPixelType == PFD_TYPE_RGBA) {
  336.     /*
  337.     ** Fill the logical paletee with RGB color ramps
  338.     */
  339.     int redMask = (1 << pfd.cRedBits) - 1;
  340.     int greenMask = (1 << pfd.cGreenBits) - 1;
  341.     int blueMask = (1 << pfd.cBlueBits) - 1;
  342.     int i;
  343.  
  344.     for (i=0; i<paletteSize; ++i) {
  345.         pPal->palPalEntry[i].peRed =
  346.             (((i >> pfd.cRedShift) & redMask) * 255) / redMask;
  347.         pPal->palPalEntry[i].peGreen =
  348.             (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
  349.         pPal->palPalEntry[i].peBlue =
  350.             (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
  351.         pPal->palPalEntry[i].peFlags = 0;
  352.     }
  353.     } else {
  354.     /*
  355.     ** Fill the logical palette with color ramps.
  356.     **
  357.     ** Set up the logical palette so that it can be realized
  358.     ** into the system palette as an identity palette.
  359.     **
  360.     ** 1) The default static entries should be present and at the right
  361.     **    location.  The easiest way to do this is to grab them from
  362.     **    the current system palette.
  363.     **
  364.     ** 2) All non-static entries should be initialized to unique values.
  365.     **    The easiest way to do this is to ensure that all of the non-static
  366.     **    entries have the PC_NOCOLLAPSE flag bit set.
  367.     */
  368.     int numRamps = NUM_COLORS;
  369.     int rampSize = (paletteSize - 20) / numRamps;
  370.     int extra = (paletteSize - 20) - (numRamps * rampSize);
  371.     int i, r;
  372.  
  373.     /*
  374.     ** Initialize static entries by copying them from the
  375.     ** current system palette.
  376.     */
  377.     GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
  378.  
  379.     /*
  380.     ** Fill in non-static entries with desired colors.
  381.     */
  382.     for (r=0; r<numRamps; ++r) {
  383.         int rampBase = r * rampSize + 10;
  384.         PALETTEENTRY *pe = &pPal->palPalEntry[rampBase];
  385.         int diffSize = (int) (rampSize * colors[r].ratio);
  386.         int specSize = rampSize - diffSize;
  387.  
  388.         for (i=0; i<rampSize; ++i) {
  389.         GLfloat *c0, *c1;
  390.         GLint a;
  391.  
  392.         if (i < diffSize) {
  393.             c0 = colors[r].amb;
  394.             c1 = colors[r].diff;
  395.             a = (i * 255) / (diffSize - 1);
  396.         } else {
  397.             c0 = colors[r].diff;
  398.             c1 = colors[r].spec;
  399.             a = ((i - diffSize) * 255) / (specSize - 1);
  400.         }
  401.  
  402.         pe[i].peRed = (BYTE) (a * (c1[0] - c0[0]) + 255 * c0[0]);
  403.         pe[i].peGreen = (BYTE) (a * (c1[1] - c0[1]) + 255 * c0[1]);
  404.         pe[i].peBlue = (BYTE) (a * (c1[2] - c0[2]) + 255 * c0[2]);
  405.         pe[i].peFlags = PC_NOCOLLAPSE;
  406.         }
  407.  
  408.         colors[r].indexes[0] = rampBase;
  409.         colors[r].indexes[1] = rampBase + (diffSize-1);
  410.         colors[r].indexes[2] = rampBase + (rampSize-1);
  411.     }
  412.  
  413.     /*
  414.     ** Initialize any remaining non-static entries.
  415.     */
  416.     for (i=0; i<extra; ++i) {
  417.         int index = numRamps*rampSize+10+i;
  418.         PALETTEENTRY *pe = &pPal->palPalEntry[index];
  419.  
  420.         pe->peRed = (BYTE) 0;
  421.         pe->peGreen = (BYTE) 0;
  422.         pe->peBlue = (BYTE) 0;
  423.         pe->peFlags = PC_NOCOLLAPSE;
  424.     }
  425.     }
  426.  
  427.     hPalette = CreatePalette(pPal);
  428.     free(pPal);
  429.  
  430.     if (hPalette) {
  431.     SelectPalette(hDC, hPalette, FALSE);
  432.     RealizePalette(hDC);
  433.     }
  434. }
  435.  
  436. void
  437. setupPixelFormat(HDC hDC)
  438. {
  439.     PIXELFORMATDESCRIPTOR pfd = {
  440.     sizeof(PIXELFORMATDESCRIPTOR),    /* size of this pfd */
  441.     1,                /* version num */
  442.     PFD_SUPPORT_OPENGL,        /* support OpenGL */
  443.     0,                /* pixel type */
  444.     0,                /* 8-bit color depth */
  445.     0, 0, 0, 0, 0, 0,        /* color bits (ignored) */
  446.     0,                /* no alpha buffer */
  447.     0,                /* alpha bits (ignored) */
  448.     0,                /* no accumulation buffer */
  449.     0, 0, 0, 0,            /* accum bits (ignored) */
  450.     16,                /* depth buffer */
  451.     0,                /* no stencil buffer */
  452.     0,                /* no auxiliary buffers */
  453.     PFD_MAIN_PLANE,            /* main layer */
  454.     0,                /* reserved */
  455.     0, 0, 0,            /* no layer, visible, damage masks */
  456.     };
  457.     int SelectedPixelFormat;
  458.     BOOL retVal;
  459.  
  460.     pfd.cColorBits = colorIndexMode ? 8 : GetDeviceCaps(hDC, BITSPIXEL);
  461.  
  462.     if (colorIndexMode) {
  463.     pfd.iPixelType = PFD_TYPE_COLORINDEX;
  464.     } else {
  465.     pfd.iPixelType = PFD_TYPE_RGBA;
  466.     }
  467.  
  468.     if (doubleBuffered) {
  469.         pfd.dwFlags |= PFD_DOUBLEBUFFER;
  470.     }
  471.  
  472.     if (renderToDIB) {
  473.     pfd.dwFlags |= PFD_DRAW_TO_BITMAP;
  474.     } else {
  475.     pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
  476.     }
  477.  
  478.     SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
  479.     if (SelectedPixelFormat == 0) {
  480.     (void) MessageBox(WindowFromDC(hDC),
  481.         "Failed to find acceptable pixel format.",
  482.         "OpenGL application error",
  483.         MB_ICONERROR | MB_OK);
  484.     exit(1);
  485.     }
  486.  
  487.     retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
  488.     if (retVal != TRUE) {
  489.     (void) MessageBox(WindowFromDC(hDC),
  490.         "Failed to set pixel format.",
  491.         "OpenGL application error",
  492.         MB_ICONERROR | MB_OK);
  493.     exit(1);
  494.     }
  495. }
  496.  
  497. LRESULT APIENTRY
  498. WndProc(
  499.     HWND hWnd,
  500.     UINT message,
  501.     WPARAM wParam,
  502.     LPARAM lParam)
  503. {
  504.     switch (message) {
  505.     case WM_CREATE:
  506.     return 0;
  507.     case WM_DESTROY:
  508.     PostQuitMessage(0);
  509.     return 0;
  510.     case WM_SIZE:
  511.     if (hGLRC) {
  512.         winWidth = (int) LOWORD(lParam);
  513.         winHeight = (int) HIWORD(lParam);
  514.         if (renderToDIB) {
  515.         resizeDIB(hDC);
  516.         }
  517.         resize();
  518.         return 0;
  519.     }
  520.     case WM_PALETTECHANGED:
  521.     /*
  522.     ** Update palette mapping if this *is not* the active window.
  523.     */
  524.     if (hGLRC && hPalette && (HWND) wParam != hWnd) {
  525.         UnrealizeObject(hPalette);
  526.         SelectPalette(hDCWindow, hPalette, FALSE);
  527.         RealizePalette(hDCWindow);
  528.         redraw();
  529.         return 0;
  530.     }
  531.     break;
  532.     case WM_QUERYNEWPALETTE:
  533.     /*
  534.     ** Update palette mapping if this *is* the active window.
  535.     */
  536.     if (hGLRC && hPalette) {
  537.         UnrealizeObject(hPalette);
  538.         SelectPalette(hDCWindow, hPalette, FALSE);
  539.         RealizePalette(hDCWindow);
  540.         redraw();
  541.         return TRUE;
  542.     }
  543.     break;
  544.     case WM_PAINT:
  545.     /*
  546.     ** Update the window.  Don't use the device context returned by
  547.     ** BeginPaint as it won't have the right palette selected into it.
  548.     */
  549.     if (hGLRC) {
  550.         PAINTSTRUCT ps;
  551.  
  552.         BeginPaint(hWnd, &ps);
  553.         redraw();
  554.         EndPaint(hWnd, &ps);
  555.         return 0;
  556.     }
  557.     break;
  558.     case WM_CHAR:
  559.     switch ((int)wParam) {
  560.     case VK_ESCAPE:
  561.         DestroyWindow(hWnd);
  562.         return 0;
  563.     case VK_SPACE:
  564.         if (idleFunc) {
  565.         idleFunc = NULL;
  566.         } else {
  567.         idleFunc = doRedraw;
  568.         }
  569.     default:
  570.         break;
  571.     }
  572.     break;
  573.     default:
  574.     break;
  575.     }
  576.  
  577.     /* Deal with any unprocessed messages */
  578.     return DefWindowProc(hWnd, message, wParam, lParam);
  579. }
  580.  
  581. int APIENTRY
  582. WinMain(
  583.     HINSTANCE hCurrentInst,
  584.     HINSTANCE hPreviousInst,
  585.     LPSTR lpszCmdLine,
  586.     int nCmdShow)
  587. {
  588.     WNDCLASS wndClass;
  589.     HWND hWnd;
  590.     MSG msg;
  591.  
  592.     /* Define and register a window class */
  593.     wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  594.     wndClass.lpfnWndProc = WndProc;
  595.     wndClass.cbClsExtra = 0;
  596.     wndClass.cbWndExtra = 0;
  597.     wndClass.hInstance = hCurrentInst;
  598.     wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  599.     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  600.     wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  601.     wndClass.lpszMenuName = NULL;
  602.     wndClass.lpszClassName = className;
  603.     RegisterClass(&wndClass);
  604.  
  605.     /* Create a window of the previously defined class */
  606.     hWnd = CreateWindow(
  607.     className,        /* Window class's name */
  608.     windowName,        /* Title bar text */
  609.     WS_OVERLAPPEDWINDOW |    /* The window's style */
  610.     WS_CLIPCHILDREN |
  611.     WS_CLIPSIBLINGS,
  612.     winX, winY,        /* Position */
  613.     winWidth, winHeight,    /* Size */
  614.     NULL,            /* Parent window's handle */
  615.     NULL,            /* Menu handle */
  616.     hCurrentInst,        /* Instance handle */
  617.     NULL);            /* No additional data */
  618.  
  619.     /* Map the window to the screen */
  620.     ShowWindow(hWnd, nCmdShow);
  621.  
  622.     /* Force the window to repaint itself */
  623.     UpdateWindow(hWnd);
  624.  
  625.     /* Set up for OpenGL rendering.
  626.      * The operations which follow must be performed in a specific order,
  627.      * or palette remapping may not occur properly.
  628.      */
  629.  
  630.     hDCWindow = GetDC(hWnd);
  631.  
  632.     /* hDC refers to the device context into which we will render */
  633.     hDC = renderToDIB ? CreateCompatibleDC(hDCWindow) : hDCWindow;
  634.  
  635.     /* Set up the pixel format and palette, but do not select the palette. */
  636.     setupPixelFormat(hDC);
  637.     setupPalette(hDC);
  638.  
  639.     /* Select the palette into the window first, to ensure that palette
  640.      * remapping will be performed correctly when we blit.
  641.      */
  642.     SelectPalette(hDCWindow, hPalette, FALSE);
  643.     RealizePalette(hDCWindow);
  644.  
  645.     /* If rendering to a DIB, select the palette first, then the bitmap. */
  646.     if (renderToDIB) {
  647.     SelectPalette(hDC, hPalette, FALSE);
  648.     RealizePalette(hDC);
  649.  
  650.     /* Create the DIB and select into the device context */
  651.     setupDIB(hDC);
  652.     }
  653.  
  654.     /* Create the rendering context, bind it, and away we go! */
  655.     hGLRC = wglCreateContext(hDC);
  656.     wglMakeCurrent(hDC, hGLRC);
  657.     init();
  658.     idleFunc = doRedraw;
  659.  
  660.     /* Process Messages */
  661.     while (1) {
  662.     /* execute the idle function while there are no messages to process */
  663.     while (idleFunc &&
  664.            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE)
  665.     {
  666.         (*idleFunc)();
  667.     }
  668.     if (GetMessage(&msg, NULL, 0, 0) != TRUE) {
  669.         break;
  670.     }
  671.     TranslateMessage(&msg);
  672.     DispatchMessage(&msg);
  673.     }
  674.  
  675.     /*
  676.     ** Finish OpenGL rendering.
  677.     */
  678.     idleFunc = NULL;
  679.     if (hGLRC) {
  680.     wglMakeCurrent(NULL, NULL);
  681.     wglDeleteContext(hGLRC);
  682.     }
  683.     ReleaseDC(hWnd, hDC);
  684.  
  685.     return msg.wParam;
  686. }
  687. 
  688.